package dictx

import "sync"

type Dictionary[K comparable, V any] struct {
	mutex    sync.RWMutex
	data     map[K]V
	onSet    func(key K, value V)
	onDelete func(key K, value V)
}

func New[K comparable, V any]() *Dictionary[K, V] {
	return &Dictionary[K, V]{
		data: map[K]V{},
	}
}

// 不会触发onSet和onDelete
func (set *Dictionary[K, V]) Reset(data map[K]V) {
	// 不会
	set.mutex.Lock()
	set.data = data
	set.mutex.Unlock()
}

func (set *Dictionary[K, V]) OnSet(handler func(key K, value V)) {
	set.onSet = handler
}

func (set *Dictionary[K, V]) OnDelete(handler func(key K, value V)) {
	set.onDelete = handler
}
func (set *Dictionary[K, V]) Set(key K, value V) {
	set.mutex.Lock()
	set.set(key, value)
	set.mutex.Unlock()
}

func (set *Dictionary[K, V]) set(key K, value V) {
	set.data[key] = value
	if set.onSet != nil {
		set.onSet(key, value)
	}
}

func (set *Dictionary[K, V]) SetByMap(m map[K]V) {
	set.mutex.Lock()
	for key, value := range m {
		set.set(key, value)
	}
	set.mutex.Unlock()
}

func (set *Dictionary[K, V]) SetBySet(other IDictionary[K, V]) {
	set.mutex.Lock()

	for key, value := range other.GetData() {
		set.set(key, value)
	}
	set.mutex.Unlock()
}
func (set *Dictionary[K, V]) GetData() map[K]V {
	return set.data
}
func (set *Dictionary[K, V]) Get(key K) (V, bool) {
	set.mutex.RLock()
	value, ok := set.data[key]
	set.mutex.RUnlock()
	return value, ok
}
func (set *Dictionary[K, V]) Has(key K) bool {
	set.mutex.RLock()
	_, ok := set.data[key]
	set.mutex.RUnlock()
	return ok
}
func (set *Dictionary[K, V]) MustGet(key K) V {
	set.mutex.RLock()
	value := set.data[key]
	set.mutex.RUnlock()
	return value
}

// 与other集合组合成新集合，相同键值时，other覆盖set
func (set *Dictionary[K, V]) Combine(other IDictionary[K, V]) {
	set.mutex.Lock()
	for key, value := range set.data {
		set.set(key, value)
	}
	set.mutex.Unlock()
}

func (set *Dictionary[K, V]) Delete(key K) {
	set.mutex.Lock()
	set.delete(key)
	set.mutex.Unlock()
}

func (set *Dictionary[K, V]) Clear() {
	set.mutex.Lock()
	if set.onDelete != nil {
		for key, value := range set.data {
			set.onDelete(key, value)
		}
	}
	set.data = map[K]V{}
	set.mutex.Unlock()
}

func (set *Dictionary[K, V]) delete(key K) {
	value, has := set.data[key]
	if !has {
		return
	}
	if set.onDelete != nil {
		set.onDelete(key, value)
	}
	delete(set.data, key)
}

func (set *Dictionary[K, V]) Exists(key K) bool {
	set.mutex.RLock()
	_, ok := set.data[key]
	set.mutex.RUnlock()
	return ok
}

func (set *Dictionary[K, V]) Length() int {
	set.mutex.RLock()
	length := len(set.data)
	set.mutex.RUnlock()
	return length
}
func (set *Dictionary[K, V]) Pop(key K) (v V, exists bool) {
	set.mutex.Lock()
	v, exists = set.data[key]
	set.delete(key)
	set.mutex.Unlock()
	return v, exists
}
func (set *Dictionary[K, V]) IsEmpty() bool {
	return set.Length() == 0
}

func (set *Dictionary[K, V]) Items() (items []V) {
	l := len(set.data)
	items = make([]V, l, l)
	set.mutex.RLock()
	i := 0
	for _, item := range set.data {
		items[i] = item
		i++
	}
	set.mutex.RUnlock()
	return
}
func (set *Dictionary[K, V]) Clone() (result *Dictionary[K, V]) {
	result = New[K, V]()
	set.mutex.RLock()
	for key, item := range set.data {
		result.Set(key, item)
	}
	set.mutex.RUnlock()
	return
}
func (set *Dictionary[K, V]) Keys() (keys []K) {
	l := len(set.data)
	keys = make([]K, l, l)
	set.mutex.RLock()
	i := 0
	for key := range set.data {
		keys[i] = key
		i++
	}
	set.mutex.RUnlock()
	return
}

// 如果返回错误，迭代终止
func (set *Dictionary[K, V]) ForRange(handler func(key K, val V) (err error)) error {
	set.mutex.RLock()
	defer set.mutex.RUnlock()
	for key, val := range set.data {
		err := handler(key, val)
		if err != nil {
			return err
		}
	}

	return nil
}

// func(key string, val V) bool{}
func (set *Dictionary[K, V]) First(handler func(key K, val V) bool) (result V) {
	set.mutex.RLock()
	defer set.mutex.RUnlock()
	for key, val := range set.data {
		if handler(key, val) {
			return val
		}
	}

	return
}

// 返回符合条件的项形成的新集合
func (set *Dictionary[K, V]) Filter(cond func(key K, val V) bool, target IDictionary[K, V]) IDictionary[K, V] {
	if target == nil {
		target = &Dictionary[K, V]{}

	}
	set.mutex.RLock()
	var a = map[K]V{}
	for key, val := range set.data {
		if cond(key, val) {
			a[key] = val
		}
	}
	target.Reset(a)
	set.mutex.RUnlock()
	return target
}

func (set *Dictionary[K, V]) Count(cond func(key K, val V) bool) int {
	set.mutex.RLock()
	count := 0
	for key, val := range set.data {
		if cond(key, val) {
			count++
		}
	}
	set.mutex.RUnlock()
	return count
}

// GroupByCondition 将数据按 createKey 函数分组
// itemFactory 是一个可选的工厂函数，用于创建新的 Dictionary 实例（对应 ITEM_CLASS）
func (d *Dictionary[K, V]) GroupByCondition(createKey func(K, V) string, itemFactory func() IDictionary[K, V]) map[string]IDictionary[K, V] {
	result := make(map[string]IDictionary[K, V])
	for key, val := range d.data {
		newKey := createKey(key, val)

		dict, exists := result[newKey]
		if !exists {
			if itemFactory != nil {
				dict = itemFactory()
			} else {
				dict = New[K, V]()
			}
			result[newKey] = dict
		}

		dict.Set(key, val)
	}

	return result
}
